package org.imlinker.buddy;

import java.util.ArrayList;

import javax.swing.ImageIcon;

import org.imlinker.list.ListItem;
import org.imlinker.list.ListModel;
import org.imlinker.message.MessageItem;
import org.imlinker.message.MessageList;
import org.imlinker.util.Images;

import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.MessageTypeFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;

@SuppressWarnings("serial")
public class BuddyList extends ListModel {

	public BuddyList(final XMPPConnection connection, MessageList messageList) {
		this.roster = connection.getRoster();

		fullList = new ArrayList<ListItem>();

		this.messageList = messageList;
		chatProxy = new ChatProxy(connection, messageList);

		// 读取用户列表。
		loadBuddyList();

		// 读取最新的状态
		for (RosterEntry entry : roster.getEntries()) {
			Presence presence = roster.getPresence(entry.getUser());
			this.changeBuddyStatus(presence);
		}

		addListener(connection);
	}

	public void addListener(final XMPPConnection connection) {
		connection.addPacketListener(new PacketListener() {
			public void processPacket(final Packet p) {
				changeBuddyStatus((Presence) p);
			}

		}, new PacketTypeFilter(Presence.class));

		// 监听消息
		connection.addPacketListener(new PacketListener() {

			public void processPacket(Packet p) {

				Message m = (Message) p;

				if (m.getBody() != null) {
					String from = m.getFrom();
					if (from.indexOf("/") >= 0) {
						from = from.substring(0, from.indexOf("/"));
					}

					final String temp = from;
					boolean chatWindowNotCreated = createChatWindow(from,
							false, m.getBody());
					if (chatWindowNotCreated) {
						messageList.addMessage(new MessageItem("Chat from "
								+ from, "chat:" + from) {
							public void open() {
								createChatWindow(temp, true, null);
							}
						});
					}
				}
			}

		}, new MessageTypeFilter(Message.Type.chat));
	}

	public boolean createChatWindow(String from, boolean b, String body) {
		return chatProxy.createChatWindow(from, b, body);
	}

	@Override
	public void openItem(ListItem item) {
		createChatWindow(item.getName(), true, null);
	}

	private void changeBuddyStatus(final Presence presence) {
		String userWithResource = presence.getFrom();
		String status = presence.getStatus();
		if (status != null && status.trim().length() > 0) {
			status = "(" + status + ")";
		} else {
			status = null;
		}

		ImageIcon icon = getIconByPresence(presence);

		for (int i = 0; i < fullList.size(); i++) {
			ListItem item = fullList.get(i);
			if (userWithResource.startsWith(item.getName())) {

				// 如果状态文字改变的话
				if (status != null) {
					RosterEntry entry = roster.getEntry(item.getName());
					if (entry.getName() == null) {
						String user = entry.getUser();

						item.setTitle(user.substring(0, user.indexOf("@"))
								+ status);
					} else {
						item.setTitle(entry.getName() + status);
					}
				}

				item.setIcon(icon);
				if (i < onlines && icon != Images.getUnAvailableIcon()) {
					this.set(i, item);

				} else {

					this.removeElement(item);
					if (icon == Images.getUnAvailableIcon()) {
						this.addElement(item);

						if (i < onlines) {
							onlines--;
						}
					} else {
						this.add(0, item);
						onlines++;
					}
				}
				break;
			}
		}
	}

	private ImageIcon getIconByPresence(final Presence presence) {

		if (presence.getType() == Presence.Type.unavailable) {
			return Images.getUnAvailableIcon();
		}

		Presence.Mode mode = presence.getMode();
		if (mode == Presence.Mode.away) {
			return Images.getAwayIcon();
		} else if (mode == Presence.Mode.dnd) {
			return Images.getDndIcon();
		} else if (mode == Presence.Mode.xa) {
			return Images.getDndIcon();
		}

		return Images.getAvailableIcon();
	}

	private void loadBuddyList() {
		fullList.clear();
		this.clear();

		for (RosterEntry entry : roster.getEntries()) {
			String user = entry.getUser();
			String name = entry.getName();

			if (name == null) {
				fullList.add(new ListItem(Images.getUnAvailableIcon(), user
						.substring(0, user.indexOf("@")), user));
			} else {
				fullList.add(new ListItem(Images.getUnAvailableIcon(), name,
						user));
			}
		}

		onlines = refreshList();
	}

	private int refreshList() {
		this.clear();

		ListItem item;
		int onlines = 0;
		for (int i = 0; i < fullList.size(); i++) {
			item = fullList.get(i);
			if (item.getIcon() != Images.getUnAvailableIcon()) {
				this.addElement(item);
				onlines++;
			}
		}

		for (int i = 0; i < fullList.size(); i++) {
			item = fullList.get(i);
			if (item.getIcon() == Images.getUnAvailableIcon()) {
				this.addElement(item);
			}
		}

		return onlines;
	}

	private ArrayList<ListItem> fullList;

	private Roster roster;

	private ChatProxy chatProxy;

	private MessageList messageList;

	private int onlines = 0;

}
